import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import axios from 'axios'
import { useUserStore } from '@renderer/store/modules/user'
import { ElLoading } from 'element-plus'

const userStore = useUserStore()

interface AxiosRequestConfigExtends extends AxiosRequestConfig {
  /** 是否跳过错误处理 */
  skipErrorHandler?: boolean
}

type LoadingType =
  | {
      close: () => void
      [key: string]: any
    }
  | undefined

export default class Axios {
  /** 属性或方法前面加上#,为私有属性或方法，只能由类的内部访问，实例无法访问，但使用时也要加# */
  #instance: AxiosInstance
  /** 全局loading效果 */
  #loading: LoadingType

  constructor(config: AxiosRequestConfigExtends) {
    /** 创建一个 Axios 实例  */
    this.#instance = axios.create(config)
    /** 添加请求拦截器 */
    this.#requestInterceptors()
    this.#responseInterceptors()
  }

  /** 请求拦截器 */
  #requestInterceptors() {
    this.#instance.interceptors.request.use((config) => {
      if (config.headers) {
        Object.assign(config.headers, {
          token: userStore.getToken,
          // lang: "",
          /** 数据是JSON，字符编码为utf-8 */
          'Content-Type': 'application/json;charset=utf-8'
        })
      }

      return config
    }, this.#onError)
  }
  /** 响应拦截器 */
  #responseInterceptors() {
    this.#instance.interceptors.response.use(
      (response: AxiosResponse<any, AxiosRequestConfigExtends>) => {
        const { data } = response
        const config = response.config as AxiosRequestConfigExtends
        this.#loading && this.#loading.close()
        /** 是否为 类文件 下载 */
        /** data.code 为 0，一般表示执行成功  */

        if (config.responseType !== 'blob' && data.code !== 200) {
          if (!config.skipErrorHandler) {
            // checkStatus(code, msg);
          }
          return Promise.reject(data)
        }

        return response
      },
      this.#onError
    )
  }

  /** 设置全屏loading */
  #setLoading() {
    this.#loading = ElLoading.service({
      lock: true,
      text: 'loading...',
      background: 'rgba(0, 0, 0, 0.5)'
    })
  }

  #onError = (error: any) => {
    this.#loading?.close && this.#loading.close()
    const { code, message, response } = error
    const isNoSkipError = !error.config?.skipErrorHandler

    if (code === 'ERR_NETWORK') {
      isNoSkipError && requestStatusHandler(code, message)
      return Promise.reject({
        code,
        msg: message
      })
    }

    if (response) {
      isNoSkipError && requestStatusHandler(response.status, message)
      return Promise.reject({
        code: response.status,
        msg: message
      })
    }
  }

  // 公用请求，get与post都会到这里
  async #request<T>(options: AxiosRequestConfigExtends) {
    try {
      const response = await this.#instance.request(options)
      return response.data as T
    } catch (error) {
      // async 函数中 throw 相当于 reject，外部可以捕获
      throw error
    }
  }

  /** GET 请求 */
  public get<T = any>(config: AxiosRequestConfigExtends, isLoading?: boolean) {
    isLoading && this.#setLoading()
    return this.#request<T>({ ...config, method: 'GET' })
  }

  /** POST 请求 */
  public post<T = any>(config: AxiosRequestConfigExtends, isLoading?: boolean) {
    isLoading && this.#setLoading()
    const configData = {
      platform: 'pc',
      version: '1.0'
    }
    if (config.data) {
      // 处理分页
      if (isObject(config.data)) {
        const { page, pageSize, ...restObj } = config.data
        config.data = Object.assign(configData, {
          data: restObj,
          page: page || '',
          pageSize: pageSize || ''
        })
      } else if (!config.headers) {
        config.data = {
          data: config.data,
          ...configData
        }
      }
    } else {
      config.data = Object.assign({}, configData)
    }
    return this.#request<T>({ ...config, method: 'POST' })
  }
}
